package org.gvp.common.constant;

import org.gvp.common.http.Page;
import org.gvp.common.http.query.DateRange;
import org.gvp.common.http.query.PagingDateRange;

import java.util.List;

/**
 * <li>全局服务层接口,此接口处理各种需要业务操作</li>
 * <li>该接口处理复杂需求操作,所有的操作都在此接口实现</li>
 * <ul>
 *     <li>增加数据方法前缀: save </li>
 *     <li>删除数据方法前缀: remove </li>
 *     <li>修改数据方法前缀: edit </li>
 *     <li>查找数据方法前缀: find </li>
 *     <li>请求列表数据方法前缀: findList </li>
 *     <li>请求分页数据方法前缀: findPage </li>
 * </ul>
 * @param <T> 数据库实体类数据类型
 * @author gvp
 * @since 2024-02-25 20:09
 * @version 1.2
 */
public interface BaseService<T> {
    /**
     * [ 默认实现 ]
     * 添加一条数据信息
     * @param pojo 数据实体对象
     * @return 反回值大于0表示添加成功,否则添加失败
     */
    default int save(T pojo){
        return 0 ;
    }
    /**
     * 添加一条数据信息,并返回添加成功后的数据,添加成功后从数据库查找添加的数据
     * @param pojo 数据实体对象
     * @return 返回添加成功后的数据,如果添加失败,则返回null
     */
    default T saveAndReturn(T pojo){return null ;}
    /**
     * [ 默认实现 ]
     * 根据数据的编号(ID)删除数据信息
     * @return 删除的数据行数量
     */
    default int removeById(Integer id){
        return 0;
    }
    /**
     * [ 默认实现 ]
     * 逻辑删除数据,根据数据编号(ID)删除数据信息
     */
    default int logicalRemove(Integer id){
        return 0;
    }
    /**
     * [ 默认实现 ]
     * 根据数据编号(ID),恢复逻辑删除的数据
     */
    default int recoverRemove(Integer id){
        return 0;
    }
    /**
     * [ 默认实现 ]
     * 修改数据,默认修改所有非空字段,不会修改数据id,根据id进行修改
     * @param pojo 需要修改的数据必须包含id字段
     * @return 修改的数据行数量
     */
    default int edit(T pojo){
        return 0;
    }
    /**
     * 修改数据,默认修改所有非空字段,不会修改数据id,根据id进行修改,修改成功后返回修改后的数据
     * @param pojo 需要修改的数据必须包含id字段
     * @return 修改成功后返回修改后的数据,如果修改失败,则返回null
     */
    default T editAndReturn(T pojo){
        return null;
    }
    /**
     * [ 默认实现 ]
     * 根据数据编号(ID)查找数据信息 [默认实现]
     */
    default T findById(Integer id){
        return null;
    }
    /**
     * [ 默认实现 ]
     * 查找所有数据列表,不包含逻辑删除的数据
     * @return 返回查找到的数据列表,如果没有查找到数据,则返回null
     */
    default List<T> findList(){
        return null;
    }
    /**
     * [ 默认实现 ]
     * 查找指定条数的数据列表
     * @param size 查找数据的条目数
     * @return 返回查找到的数据列表,如果没有查找到数据,则返回null
     */
    default List<T> findLimit(int size){
        return null;
    }
    /**
     * [ 默认实现 ]
     * 查找指定条数的数据列表
     * @param start 查找开始位置
     * @param end 查找结束位置
     * @return 返回查找到的数据列表,如果没有查找到数据,则返回null
     */
    default List<T> findLimit(int start, int end){
        return null;
    }
    /**
     * [ 默认实现 ]
     * 查找指定条数的数据列表,根据日期范围查找数据
     * @param start 开始位置
     * @param end 结束位置
     * @param dateStart 开始日期
     * @param dateEnd 结束日期
     * @return 返回查找到的数据列表,如果没有查找到数据,则返回null
     */
    default List<T> findLimit(int start, int end, String dateStart,String dateEnd){
        return null;
    }
    /**
     * [ 默认实现 ]
     * 查找指定条数的数据列表,默认查找 * ,查找不包含逻辑删除的数据
     * @param field 指定要查找的数据量的字段,默认为 *
     */
    default Long findCount(String field){
        return null;
    }
    /**
     * [ 默认实现 ]
     * 查找全部数据的数量,不包含逻辑删除的数据
     */
    default Long findCount(){
        return this.findCount("*") ;
    }

    /**
     * 查找指定日期范围的数据数量
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 返回查找到的数据数量
     */
    default Long findCountRange(String startDate, String endDate){
        return null;
    }
    /**
     * [ 默认实现 ]
     * 查找分页数据列表,此方法会直接调用repository层对象执行查找
     * @param currentPage 当前页
     * @param pageSize 每页显示数据条数
     * @return 返回分页数据对象
     */
    default Page<T> findPage(int currentPage, int pageSize){
        return Page.<T>builder()
                .total(this.findCount())
                .current(currentPage)
                .pageSize(pageSize)
                .build(this::findLimit);
    }
    /**
     * 查找分页数据列表,根据月份查找数据
     * @param currentPage 当前页
     * @param pageSize 每页显示数据条数
     * @param month 月份,查找当前年份的month月的数据
     */
    default Page<T> findPage(int currentPage, int pageSize,int month){
        DateRange dateRange = DateRange.ofMonth(month);
        return this.findPage(currentPage,pageSize,dateRange);
    }
    /**
     * [ 默认实现 ]
     * 查找分页数据列表,根据年份和月份查找数据
     * @param currentPage 当前页
     * @param pageSize 每页显示数据条数
     * @param year 年份
     * @param month 月份
     */
    default Page<T> findPage(int currentPage, int pageSize, int year, int month){
        DateRange dateRange = DateRange.ofYearMonth(year, month);
        return this.findPage(currentPage,pageSize,dateRange);
    }
    /**
     * [ 默认实现 ]
     * 查找分页数据列表,根据日期范围查找数据
     * @param currentPage 当前页
     * @param pageSize 每页显示数据条数
     * @param range 日期范围
     */
    default Page<T> findPage(int currentPage, int pageSize, DateRange range){
        PagingDateRange pagingDateRange = PagingDateRange.of(currentPage, pageSize, range.getStartDate(),range.getEndDate());
        return this.findPage(pagingDateRange);
    }
    /**
     * [ 默认实现 ]
     * 查找分页数据列表,根据日期范围查找分页数据,此方法会直接调用repository层对象执行查找
     * @param range 日期范围分页对象
     */
    default Page<T> findPage(PagingDateRange range){
        return Page.<T>builder()
                .total(this.findCount())
                .dateRange(range)
                .<T>buildRange(this::findLimit);
    }

}
